import { isDefNaN, isNum, isDef, is_Object_or_Array } from './whether';

/**
 * @function 查询目标源
 * @param {any} source 目标对象
 * @param {String|Number} targetPath 目标路径
 * @param {any} defaultValue 未找到返回的默认值
 * @returns {any}
 */
export default function takeAt(source, targetPath, defaultValue = undefined) {
  // 判断是不是对象或数组，如果都不是就返回目标对象
  // Judge whether it is an object or array. If it is not an object or array, return the target object
  if (!is_Object_or_Array(source)) return source;
  // 如果路径不是字符串或者不是数字则返回默认值
  // If the path is not a string or a number, the default value is returned
  if (!['string', 'number'].includes(typeof targetPath) && !isDefNaN(targetPath)) return defaultValue;
  // 获取目标对象
  // Get target object
  let target = source;
  // 转换传入目标路径(如果是数字需要转换)
  // Convert the incoming destination path (if it is a number, it needs to be converted)
  const handlePath = isNum(targetPath) ? targetPath.toString() : targetPath;
  // 将路径格式转数组
  // Convert path format to array
  const formatField = handlePath.replace(/(\[|\])/gi, a => (a === '[' ? '.' : '')).split('.');

  // 循环查找
  // Circular search
  for (let i = 0, len = formatField.length; i < len; i++) {
    const field = formatField[i];
    if (isDef(target[field])) {
      target = target[field];
    } else {
      target = defaultValue;
      break;
    }
  }
  return target;
}
